package com.joysuch.wwyt.attendant.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.attendant.bean.*;
import com.joysuch.wwyt.attendant.bean.vo.*;
import com.joysuch.wwyt.attendant.entity.*;
import com.joysuch.wwyt.attendant.enums.AttendantStateEnum;
import com.joysuch.wwyt.attendant.enums.ProcessStatusEnum;
import com.joysuch.wwyt.attendant.mapper.AttendantRecordMapper;
import com.joysuch.wwyt.attendant.service.*;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.SimpleDateFormatCache;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.exception.ApiCoreException;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.util.DateUtils;
import com.joysuch.wwyt.workflow.api.bean.PersonTrajectoryResp;
import com.joysuch.wwyt.workflow.api.service.PersonTrajectoryService;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description //TODO
 * @Date 2023/2/15 11:47
 * @Author Leong
 **/
@Service
@Transactional(rollbackFor = Exception.class)
public class AttendantRecordServiceImpl extends ServiceImpl<AttendantRecordMapper, AttendantRecord> implements AttendantRecordService {

    @Resource
    private BaseUserDao baseUserDao;
    @Autowired
    private AttendantAreaService attendantAreaService;

    @Autowired
    private AttendantPlanService attendantPlanService;

    @Autowired
    private AttendantPlanContentService attendantPlanContentService;

    @Autowired
    private AttendantRecordProcessService attendantRecordProcessService;

    @Autowired
    private PersonTrajectoryService personTrajectoryService;

    @Resource
    private OpenPlatformService openPlatformService;

    @Autowired
    private BaseConfigService baseConfigService;

    @Override
    public ResultBean findPage(AttendantRecordSearchBean searchBean) {
        List<AttendantRecordPageVo> voList = new ArrayList<>();
        List<Long> userIds = new ArrayList<>();
        Page<AttendantRecordPageVo> page = new Page<>(searchBean.getPage() + 1, searchBean.getSize());
        if (StringUtils.isNotBlank(searchBean.getUserName())) {
            userIds = baseUserDao.findIdsByRealName(searchBean.getUserName());
            if (CollectionUtils.isEmpty(userIds)) {
                return ResultBean.pageData(voList, 0);
            }
        }
        if (searchBean.getJobId() != null) {
            List<Long> jobUserIds = baseUserDao.findAllUserByJob(searchBean.getJobId());
            if (CollectionUtils.isEmpty(jobUserIds)) {
                return ResultBean.pageData(voList, 0);
            }
            userIds.addAll(jobUserIds);
        }
        userIds = userIds.stream().distinct().collect(Collectors.toList());
        Page<AttendantRecordPageVo> pageData = baseMapper.findPage(page, userIds, searchBean.getPlanName(), searchBean.getAreaId(),searchBean.getStartTime(),searchBean.getEndTime(), Context.getCompanyCode(), Context.getCurrentTenantId());
        List<AttendantRecordPageVo> records = pageData.getRecords();
        for (AttendantRecordPageVo record : records) {
           int isFindDanger=0;
            if (record.getAttendantPlanId()!=null) {
                int count = attendantRecordProcessService.count(new QueryWrapper<AttendantRecordProcess>().eq("data_source_id",record.getAttendantPlanId()));
                //是否有隐患
                if (count > 0){
                    isFindDanger=1;
                }
            }
            record.setIsFindDanger(isFindDanger);

        }
        return ResultBean.pageData(records, page.getTotal());
    }

    @Override
    public AttendantRecordDetailVo detail(Long id) {
        AttendantRecordDetailVo vo = baseMapper.detail(id);
        if (vo != null){
            //暂存状态，去除完成时间
            if (vo.getState().equals(AttendantStateEnum.STAGING.getValue())){
                vo.setFinishTime(null);
            }
            List<AttendantPlanContent> contents = attendantPlanContentService.selectByPlanId(vo.getAttendantPlanId());
            vo.setContentList(contents);
            List<AttendantRecordProcessBean> process = attendantRecordProcessService.selectProcessByPlanId(vo.getAttendantPlanId());
            for (AttendantRecordProcessBean processBean : process) {
                BeanUtils.copyProperties(process,processBean);
                if (processBean.getProcessStatus()!=null) {
                    processBean.setProcessStatusName(ProcessStatusEnum.find(processBean.getProcessStatus()).getDesc());
                }
            }
            vo.setProcessList(process);
//            vo.setProcessList(attendantRecordProcessService.selectProcessByPlanId(vo.getAttendantPlanId()));
        }
        return vo;
    }

    @Override
    public ResultBean track(Long id) throws IllegalArgumentException {
        BaseConfig ipConfig = baseConfigService.findConfig(Context.getCurrentTenantId(), Context.getCurrentOrgCode(), BaseConfigCodes.OPEN_SERVICE_SERVER_URL);
        if (ipConfig==null||StringUtils.isBlank(ipConfig.getValue())){
            Map<String,String> map=new HashMap<>();
            map.put("errCode","2110");
            map.put("errMsg","系统未配置开放平台地址，无法查询轨迹");
            return     ResultBean.success(map);
//            throw new IllegalArgumentException("系统未配置开放平台地址，无法查询轨迹");
        }

        AttendantRecordTrackVo vo = baseMapper.track(id);
        if (vo == null){
            Map<String,String> map=new HashMap<>();
            map.put("errCode","2110");
            map.put("errMsg","跟班记录不存在！");
            return     ResultBean.success(map);
//            throw new IllegalArgumentException("跟班记录不存在！");
        }
        BaseUser baseUser = baseUserDao.findById(vo.getUserId()).get();
        if (baseUser!=null&& StringUtils.isBlank(baseUser.getSn())) {
            Map<String,String> map=new HashMap<>();
            map.put("errCode","2110");
            map.put("errMsg","人员未绑定定位卡，无法查询轨迹");
            return      ResultBean.success(map);
//            throw new IllegalArgumentException("人员未绑定定位卡，无法查询轨迹");
        }
        String sn = getUserSn(vo.getUserId());
        String requestId = IdUtil.simpleUUID();
        if (vo.getSignInTime() != null && vo.getFinishTime() != null){
            try {
                List<PersonTrajectoryResp> personTrajectoryList = personTrajectoryService.getPersonTrajectoryPoints(sn, vo.getSignInTime().getTime(),vo.getFinishTime().getTime(), vo.getAttendantPlanId().toString(), requestId);
                vo.setTrajectoryRespList(personTrajectoryList);
            } catch (ApiCoreException e) {
                throw new RuntimeException(e);
            }
        }

        AttendantArea attendantArea = attendantAreaService.getById(vo.getAreaId());
        vo.setIsSync(attendantArea.getIsSync());
        vo.setCoordinates(attendantArea.getCoordinates());
        PersonStayTimeReq req = new PersonStayTimeReq();
        req.setMacs(Lists.newArrayList(sn));
        req.setRailId(attendantArea.getPlatformAreaId());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String attendantTimeStr = sdf.format(vo.getAttendantTime());
        String starTimeStr = attendantTimeStr+" " + vo.getStartTime().toString();
        String endTimeStr = attendantTimeStr + " " + vo.getEndTime().toString();
        if (vo.getEndTime().before(vo.getStartTime())) {
            String addDayTimeStr = sdf.format(DateUtils.getDate(vo.getAttendantTime(), 1));
            endTimeStr = addDayTimeStr + " " + vo.getEndTime().toString();
        }
        long starTime=0L;
        long endTime=0L;
        try {
            if (vo.getSignInTime()==null) {
                starTime=  sdf2.parse(starTimeStr).getTime();
            }else {
                starTime=vo.getSignInTime().getTime();
            }
            if (vo.getFinishTime()==null) {
                endTime=  sdf2.parse(endTimeStr).getTime();
            }else {
                endTime= vo.getFinishTime().getTime();
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        req.setStartTime(starTime);
        req.setEndTime(endTime);
        if (vo.getIsSync()==0) {
            vo.setDuration("");
            vo.setTimes(null);
            return ResultBean.success(vo);
        }
        List<AttendantTimeVo> vos=new ArrayList<>();
        if (StringUtils.isNotBlank(vo.getAccessTime())) {
            vos= JSONArray.parseArray(vo.getAccessTime(),AttendantTimeVo.class);
            vo.setTimes(vos);
            return ResultBean.success(vo);
        }
        if (attendantArea.getIsSync()==1) {
            try {
                List<PersonStayTimeResp> stayTimeResps = openPlatformService.railStayTime(req, attendantArea.getTenentId(), attendantArea.getOrgCode());
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(stayTimeResps)){
                    long duration=0;
                    for (PersonStayTimeResp stayTimeResp : stayTimeResps) {
                        if (stayTimeResp != null&&stayTimeResp.getDuration()>0){
                            if (stayTimeResp.getDuration()>0) {
                                duration=  duration+stayTimeResp.getDuration();
                            }
                            AttendantTimeVo attendantTimeVo = new AttendantTimeVo();
                            if (stayTimeResp.getDurationEndTime()>0) {
                                attendantTimeVo.setOutTime(new Date(stayTimeResp.getDurationEndTime()));
                            }
                            if (stayTimeResp.getDurationStartTime()>0) {
                                attendantTimeVo.setInTime(new Date(stayTimeResp.getDurationStartTime()));
                                vos.add(attendantTimeVo);
                            }
                        }
                    }
                    SimpleDateFormat dateFormat = SimpleDateFormatCache.getHms();
                    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
                    if (duration>0){
                        vo.setDuration(dateFormat.format(duration));
                    }
                }
                vo.setTimes(vos);
            } catch (ApiCoreException e) {
                e.printStackTrace();
            }
        }
        return ResultBean.success(vo);
    }

    @Override
    public void delete(Long id) {
        AttendantRecord record = new AttendantRecord();
        record.setDeleteFlag("1");
        baseMapper.update(record,new UpdateWrapper<AttendantRecord>().eq("id",id));
    }

    @Override
    public String stay(Long id) {
        AttendantRecord attendantRecord = baseMapper.selectById(id);
        if (attendantRecord == null){
            return null;
        }
        if (Strings.isNotEmpty(attendantRecord.getDuration())) {
            return attendantRecord.getDuration();
        }
        AttendantPlan plan = attendantPlanService.getById(attendantRecord.getAttendantPlanId());
        String sn = getUserSn(plan.getUserId());
        String railId = attendantAreaService.findRailId(plan.getAreaId());
        //获取停留时常
        PersonStayTimeReq req = new PersonStayTimeReq();
        req.setMacs(Lists.newArrayList(sn));
        req.setRailId(railId);
        req.setStartTime(attendantRecord.getSignInTime().getTime());
        req.setEndTime(attendantRecord.getFinishTime().getTime());
        try {
            List<PersonStayTimeResp> stayTimeResps = openPlatformService.railStayTime(req,attendantRecord.getTenentId(),attendantRecord.getOrgCode());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(stayTimeResps)){
                long duration=0;
                for (PersonStayTimeResp stayTimeResp : stayTimeResps) {
                    if (stayTimeResp != null&&stayTimeResp.getDuration()>0){
                        if (stayTimeResp.getDuration()>0) {
                            duration=  duration+stayTimeResp.getDuration();
                        }
                    }
                }
                SimpleDateFormat dateFormat = SimpleDateFormatCache.getHms();
                dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
                if (duration>0){
                    return dateFormat.format(duration);
                }
            }
        } catch (ApiCoreException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    @Override
    public List<AttendantStayTimeBean> findNoDuration() {
        return baseMapper.findNoDuration();
    }

    @Override
    public void updateDuration(Long id, String duration) {
         baseMapper.updateDuration(id,duration);
    }

    @Override
    public AttendantRecord selectByPlanId(Long id) {
        AttendantRecord attendantRecord = baseMapper.selectByPlanId(id);
        return attendantRecord;
    }

    /**
     * 获取用户sn号
     *
     * @param userId
     * @return
     */
    private String getUserSn(Long userId) {
        String sn = null;
        Optional<BaseUser> optionalUser = baseUserDao.findById(userId);
        if (optionalUser.isPresent()) {
            BaseUser baseUser = optionalUser.get();
            sn = baseUser.getSn();
        }
        return sn;
    }

    @Override
    public ResultBean selectPage(Pageable pageable, Integer way) {
        Page<AttendantRecordAppBean> page = new Page<>(pageable.getPageNumber() + 1, pageable.getPageSize());
        Date yesterday=null;
        if (way==null) {
            way=1;
        }
        if (way==1){
            yesterday = DateUtils.getYesterday();
        }
        Map<String, Date> map = DateUtils.getTime(way);
        Long userId = Context.getCurrentUserId();
        Page<AttendantRecordAppBean> resultPage = baseMapper.selectPage(page, map.get("startTime"), map.get("endTime"), userId,yesterday);
        if (resultPage.getRecords() != null&&!resultPage.getRecords().isEmpty()) {
            List<Long> areaIds = resultPage.getRecords().stream().map(AttendantRecordAppBean::getAreaId).distinct().collect(Collectors.toList());
            List<AttendantArea> areaList = attendantAreaService.selectByIds(areaIds);
            Map<Long, String> areaMap = areaList.stream().collect(Collectors.toMap(AttendantArea::getId, e -> e.getName()));
            for (AttendantRecordAppBean record : resultPage.getRecords()) {
                record.setAreaName(areaMap.get(record.getAreaId()));
                Integer start = Integer.parseInt(record.getStartTime().substring(0,2));
                Integer end = Integer.parseInt(record.getEndTime().substring(0,2));
                record.setStartTime(record.getStartTime().substring(0,5));
                record.setEndTime(record.getEndTime().substring(0,5));
                if (start > end) {
                    record.setEndTime(record.getEndTime() + "(次日)");
                }

                if (record.getState() != null) {
                    record.setStateName(AttendantStateEnum.find(record.getState()).getDesc());
                    if (record.getState() == 0) {
                        record.setStateName("进行中");
                    }
                }
            }
        }

        return ResultBean.pageData(resultPage.getRecords(), page.getTotal());
    }

    @Override
    public AttendantRecordAppBean findByPlanId(Long planId) {
        AttendantRecordAppBean bean = new AttendantRecordAppBean();
        AttendantPlan plan = attendantPlanService.getById(planId);
        AttendantRecord attendantRecord = baseMapper.selectByPlanId(planId);
        BeanUtils.copyProperties(plan, bean);
        bean.setId(null);
        if (attendantRecord!=null) {
            bean.setId(attendantRecord.getId());
            bean.setSignInTime(attendantRecord.getSignInTime());
            bean.setFinishTime(attendantRecord.getFinishTime());
        }
        List<AttendantRecordProcessBean> process = attendantRecordProcessService.selectProcessByPlanId(planId);
        for (AttendantRecordProcessBean processBean : process) {
            BeanUtils.copyProperties(process,processBean);
            if (processBean.getProcessStatus()!=null) {
                processBean.setProcessStatusName(ProcessStatusEnum.find(processBean.getProcessStatus()).getDesc());
            }
        }
        bean.setProcessBeans(process);
        List<AttendantPlanContent> list = attendantPlanContentService.selectByPlanId(planId);
        bean.setList(list);
        bean.setPlanId(plan.getId());
        bean.setStartTime(plan.getStartTime().toString().substring(0,5));
        bean.setEndTime(plan.getEndTime().toString().substring(0,5));
        AttendantAreaBean areaBean = attendantAreaService.findById(plan.getAreaId());
        if (areaBean!=null) {
            bean.setAreaName(areaBean.getName());
            bean.setCoordinates(areaBean.getCoordinates());
        }
        bean.setSignInMethod(plan.getSignInMethod());
        return bean;
    }

    @Override
    public void saveEntity(AttendantRecordReqAppBean bean) {
        AttendantPlan plan = attendantPlanService.getById(bean.getPlanId());
        if (plan==null||plan.getDeleteFlag().equals("1")) {
            throw new IllegalArgumentException("该跟班计划已被删除");
        }
        if (plan.getState().equals(AttendantStateEnum.NOT_STARTED.getValue())){
            throw new IllegalArgumentException("任务暂未开始，请按时开始执行");
        }
        AttendantRecord attendantRecord;
        if (bean.getId() == null) {
            attendantRecord = new AttendantRecord();
            BeanUtils.copyProperties(bean, attendantRecord);
            attendantRecord.setAttendantPlanId(bean.getPlanId());
            baseMapper.insert(attendantRecord);
        } else {
            attendantRecord = baseMapper.selectById(bean.getId());
            BeanUtils.copyProperties(bean, attendantRecord);
            baseMapper.updateById(attendantRecord);
        }

        plan.setState(bean.getState());
        attendantPlanService.updateById(plan);
        List<AttendantPlanContent> list = bean.getList();
        attendantPlanContentService.saveOrUpdateBatch(list);

        //完成任务
/*        if (bean.getState().equals(AttendantStateEnum.COMPLETED.getValue())){
            String sn = getUserSn(plan.getUserId());
            String railId = attendantAreaService.findRailId(plan.getAreaId());
            String requestId = IdUtil.simpleUUID();
            //获取停留时常
            PersonStayTimeReq req = new PersonStayTimeReq();
            req.setMacs(Lists.newArrayList(sn));
            req.setRailId(railId);
            req.setStartTime(attendantRecord.getSignInTime().getTime());
            req.setEndTime(attendantRecord.getFinishTime().getTime());
            try {
                List<PersonStayTimeResp> stayTimeResps = openPlatformService.railStayTime(req,attendantRecord.getTenentId(),attendantRecord.getOrgCode());
                if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(stayTimeResps)){
                    long duration=0;
                    for (PersonStayTimeResp stayTimeResp : stayTimeResps) {
                        if (stayTimeResp != null&&stayTimeResp.getDuration()>0){
                            if (stayTimeResp.getDuration()>0) {
                                duration=  duration+stayTimeResp.getDuration();
                            }
                        }
                    }
                    SimpleDateFormat dateFormat = SimpleDateFormatCache.getHms();
                    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
                    if (duration>0){
                        attendantRecord.setDuration(dateFormat.format(duration));
                    }
                    baseMapper.updateById(attendantRecord);
                }
            } catch (ApiCoreException e) {
                throw new RuntimeException(e);
            }
        }*/
    }

    @Override
    public void updateRecord(List<AttendantPlanContent> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        AttendantPlanContent attendantPlanContent = list.get(0);
        if (attendantPlanContent != null && attendantPlanContent.getAttendantPlanId() != null) {
            AttendantPlan attendantPlan = attendantPlanService.getById(attendantPlanContent.getAttendantPlanId());
            Date date = DateUtils.getDate(new Date(), "yyyy-MM-dd");
            Date time = DateUtils.getDate(new Date(), "HH:mm:ss");
            if (date.after(attendantPlan.getAttendantTime()) || time.after(attendantPlan.getEndTime())) {
                throw new IllegalArgumentException("跟班任务已结束, 不可修改跟班记录");
            }
        }
        attendantPlanContentService.saveOrUpdateBatch(list);
    }

}
